package com.medicinezp.api.controller;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.medicinezp.api.vo.WxLoginVo;
import com.medicinezp.common.config.MedicinezpConfig;
import com.medicinezp.common.constant.Constants;
import com.medicinezp.common.core.controller.BaseController;
import com.medicinezp.common.core.domain.AjaxResult;
import com.medicinezp.common.core.domain.entity.SysUser;
import com.medicinezp.common.core.domain.model.LoginBody;
import com.medicinezp.common.core.domain.model.LoginUser;
import com.medicinezp.common.core.redis.RedisCache;
import com.medicinezp.common.utils.AES.WXCore;
import com.medicinezp.common.utils.AES.WeiXinConfig;
import com.medicinezp.common.utils.SecurityUtils;
import com.medicinezp.common.utils.StringUtils;
import com.medicinezp.common.utils.http.HttpUtils;
import com.medicinezp.framework.web.service.SysLoginService;
import com.medicinezp.framework.web.service.TokenService;
import com.medicinezp.system.service.ISysUserService;
import io.swagger.annotations.ApiOperation;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.ibatis.util.MapUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author zl
 */
@RestController
@RequestMapping("/api")
public class LoginApiController extends BaseController {
    private static Logger logger = LoggerFactory.getLogger(LoginApiController.class);
    @Autowired
    private MedicinezpConfig medicinezpConfig;
    @Autowired
    private SysLoginService sysLoginService;
    @Autowired
    private ISysUserService userService;

    @Autowired
    private TokenService tokenService;


    @Autowired
    private RedisCache redisCache;

    @PostMapping("/noAuth/loginApp")
    public AjaxResult loginApp(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = sysLoginService.login(loginBody.getUsername(), loginBody.getPassword(),loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    @RequestMapping("/noAuth/login")
    public AjaxResult login(@RequestBody WxLoginVo wxLoginVo) {
        logger.info("登录参数：{}", JSON.toJSONString(wxLoginVo));
        AjaxResult ajax = AjaxResult.success();
        String appId = medicinezpConfig.getAppId();
        String appSecret = medicinezpConfig.getAppSecret();
        Map<String, Object> mapResult = new HashMap<>();
        if ("debug".equalsIgnoreCase(wxLoginVo.getCode())) {
            mapResult.put("openid", wxLoginVo.getCode());
        } else {
            mapResult = getWxUserOpenid(wxLoginVo.getCode(), appId, appSecret);
        }
        Object openid = mapResult.get("openid");
        String unionid = null;
        if (StringUtils.isNotNull(mapResult.get("unionid"))) {
            unionid = (String) mapResult.get("unionid");
        }
        if (StringUtils.isNull(openid)) {
            return AjaxResult.error("获取openid失败!");
        }
        logger.info("==============mapResult=======================");
        logger.info(JSONObject.toJSONString(mapResult));
        logger.info("==============mapResult=======================");

        // 生成令牌
        mapResult.put("avatar", wxLoginVo.getAvatarUrl());
        mapResult.put("sex", wxLoginVo.getGender());
        mapResult.put("nickName", wxLoginVo.getNickName());
        mapResult.put("unionid", unionid);
        Map<String, Object> map = sysLoginService.loginWeiXin(mapResult);

        return AjaxResult.success(map);

    }

    @GetMapping("/noAuth/getUserOpenid/{code}")
    public AjaxResult getUserOpenid(@PathVariable("code") String code) {
        String appId = medicinezpConfig.getAppId();
        String APPSecret = medicinezpConfig.getAppSecret();
        Map<String, Object> mapResult = new HashMap<>();
        if ("debug".equalsIgnoreCase(code)) {
            mapResult.put("openid", code);
        } else {
            mapResult = getWxUserOpenid(code, appId, APPSecret);
        }
        return AjaxResult.success(mapResult);
    }


    //获取openid
    public static Map<String, Object> getWxUserOpenid(String code, String APPID, String APPSecret) {
        //拼接url
        StringBuilder url = new StringBuilder("https://api.weixin.qq.com/sns/jscode2session?");
        url.append("appid=");
        url.append(APPID);
        url.append("&secret=");
        url.append(APPSecret);
        url.append("&js_code=");
        url.append(code);
        url.append("&grant_type=authorization_code");
        Map<String, Object> map = null;
        try {
            //构建一个Client
            HttpClient client = HttpClientBuilder.create().build();
            //构建一个GET请求
            HttpGet get = new HttpGet(url.toString());
            //提交GET请求
            HttpResponse response = client.execute(get);
            //拿到返回的HttpResponse的"实体"
            HttpEntity result = response.getEntity();
            String content = EntityUtils.toString(result);
            //打印返回的信息
            System.out.println(content);
            //把信息封装为json
            JSONObject res = JSONObject.parseObject(content);
            //把信息封装到map
            map = parseJSON2Map(res);
            logger.info(JSONObject.toJSONString(res));
        } catch (Exception e) {
            logger.error("获取OPENID失败：{}", e.getMessage());
        }
        return map;
    }

    @PostMapping("/noAuth/getWxPhoneNumber")
    public AjaxResult getPhoneNumberV2(@RequestBody  WxLoginVo wxLoginVo){
        return AjaxResult.success("", getWxPhoneNumber(wxLoginVo.getCode()));

    }

    public  JSONObject getWxPhoneNumber(String code){
        Map<String, Object> res = getAccessToken();
        String accessToken = (String) res.get("access_token");
        String url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token="+accessToken ;
        Map<String,String> data = new HashMap<>();
        data.put("code",code);
        OkHttpClient okHttpClient = new OkHttpClient();
        MediaType parse = MediaType.parse("application/json; charset=utf-8");

        okhttp3.RequestBody form = okhttp3.RequestBody.create(parse, JSONUtils.toJSONString(data));
        Request request = new Request.Builder()
                .url(url)
                .post(form)
                .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            String string = response.body().string();
            if(StringUtils.isEmpty(string)){
                return null;
            }
            JSONObject jsonObject = JSONObject.parseObject(string);
            JSONObject phone_info =(JSONObject) jsonObject.get("phone_info");
            phone_info.remove("watermark");
            return phone_info;
        } catch (IOException e) {
            logger.error("获取手机号失败：{}",e.getMessage());
            throw new RuntimeException(e);
        }
//        String s = HttpUtils.sendPost(url, null);
//        System.out.println(s);
    }


    @ApiOperation(value = "解析微信手机号")
    @PostMapping("/noAuth/getWxPhoneNumber-old")
    public AjaxResult getWxPhoneNumber(@RequestBody WeiXinConfig weiXinConfig) {
        AjaxResult ajax = AjaxResult.success();
        String appId = medicinezpConfig.getAppId();
        String APPSecret = medicinezpConfig.getAppSecret();
        Map<String, Object> mapResult = getWxUserOpenid(weiXinConfig.getCode(), appId, APPSecret);
        Object sessionKey = mapResult.get("session_key");
        String openid = String.valueOf(mapResult.get("openid"));

//        if(StringUtils.isNull(sessionKey)){
//            //测试直接传sessionkey使用
//           sessionKey = weiXinConfig.getSessionKey();
//        }
        if (StringUtils.isNull(sessionKey)) {
            return AjaxResult.error("获取openid失败!");
        }
        logger.info("=====================================sessionKey" + sessionKey);

        String result = WXCore.decrypt(appId, weiXinConfig.getEncryptedData(), String.valueOf(sessionKey), weiXinConfig.getIv());
        logger.info(result);
        JSONObject jsonObj = JSONObject.parseObject(result);
        //更新用户手机信息
        String phoneNumber = jsonObj.getString("phoneNumber");

        SysUser user = userService.selectUserByOpenId(openid);
        user.setPhonenumber(phoneNumber);
        user.setUserName(phoneNumber);
        userService.updateUser(user);
        ajax.put("data", jsonObj);
        return ajax;
    }

    public String getUnionId(String openid) {
        Map<String, Object> res = this.getAccessToken();
        String accessToken = (String) res.get("access_token");


        // 3、访问微信的资源服务器，获取用户信息
        String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
                "?access_token=%s" +
                "&openid=%s";
        String userInfoUrl = String.format(baseUserInfoUrl, accessToken, openid);
        String resultUserInfo = HttpUtils.sendGet(userInfoUrl, null);
        System.out.println(resultUserInfo);
        return null;
    }

    public Map<String, Object> getAccessToken() {
        Map<String, Object> access_token = redisCache.getCacheMap("zp_access_token");
        if (StringUtils.isNotNull(access_token) && StringUtils.isNotEmpty(access_token)) {
            return access_token;
        }
        //拼接url
        StringBuilder url = new StringBuilder("https://api.weixin.qq.com/cgi-bin/token?");
        //appid设置
        url.append("grant_type=");
        url.append("client_credential");
        //secret设置
        url.append("&appid=");
        url.append(medicinezpConfig.getAppId());
        //code设置
        url.append("&secret=");
        url.append(medicinezpConfig.getAppSecret());
        Map<String, Object> map = null;
        try {
            //构建一个Client
            HttpClient client = HttpClientBuilder.create().build();
            //构建一个GET请求
            HttpGet get = new HttpGet(url.toString());
            //提交GET请求
            HttpResponse response = client.execute(get);
            //拿到返回的HttpResponse的"实体"
            HttpEntity result = response.getEntity();
            String content = EntityUtils.toString(result);
            //打印返回的信息
            System.out.println(content);
            //把信息封装为json
            JSONObject res = JSONObject.parseObject(content);
            //把信息封装到map
            map = parseJSON2Map(res);
            redisCache.setCacheMap("zp_access_token", map);
            Integer expiresIn = (Integer) map.get("expires_in");
            int expire = expiresIn - 200;

            boolean flag = redisCache.expire("zp_access_token", Long.valueOf(expire), TimeUnit.SECONDS);
            if (!flag) {
                redisCache.deleteObject("zp_access_token");
            }


        } catch (Exception e) {
            logger.info("获取getAccessToken失败:{}", e.getMessage());
        }
        return map;
    }


    public static Map<String, Object> parseJSON2Map(JSONObject json) {
        Map<String, Object> map = new HashMap<String, Object>();
        // 最外层解析
        for (Object k : json.keySet()) {
            Object v = json.get(k);
            // 如果内层还是数组的话，继续解析
            if (v instanceof JSONArray) {
                List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
                @SuppressWarnings("unchecked")
                Iterator it = ((JSONArray) v).iterator();
                while (it.hasNext()) {
                    JSONObject json2 = (JSONObject) it.next();
                    list.add(parseJSON2Map(json2));
                }
                map.put(k.toString(), list);
            } else {
                map.put(k.toString(), v);
            }
        }
        return map;
    }
}
